#include "EventProcessor.h"

#include "Utilities.h"
#include <algorithm>

EventProcessor::EventProcessor()
{
}


EventProcessor::~EventProcessor()
{
    DisposeEvents();
}


/** 
 * Notifies the Event Generator of a new event occurred.
 * 
 * @param event: an SDL event.
 */

Event* EventProcessor::Process(const SDL_Event &event)
{
    Event* toReturn = NULL;
    
    if
    (  event.type == SDL_MOUSEBUTTONDOWN 
    || event.type == SDL_MOUSEBUTTONUP
    || event.type == SDL_MOUSEMOTION
    )
    {
	toReturn = ProcessMouseEvent( event );
    }
    else if( event.type == SDL_KEYDOWN || event.type == SDL_KEYUP )
    {
	toReturn = ProcessKeyboardEvent( event );
    }
    
    if( toReturn )
	m_eventGarbage.push_back( toReturn );
    
    return toReturn;
}


/**
 * Disposes all produced events.
 */

void EventProcessor::DisposeEvents()
{
    std::for_each( m_eventGarbage.begin( ), m_eventGarbage.end( ), FreePointer< Event >( ) );
    
    m_eventGarbage.clear( );
}



/**
 * Creates a mouse event based on an SDL_Event and returns it.
 */

MouseEvent* EventProcessor::ProcessMouseEvent(const SDL_Event &event)
{
    int occurredX = event.button.x, occurredY = event.button.y;
    
    MouseEvent* toReturn = NULL;
    
    switch( event.type )
    {
	case SDL_MOUSEBUTTONDOWN:
	{
	    MouseButton btn;
	    
	    switch( event.button.button )
	    {
		case SDL_BUTTON_LEFT:
		    btn = MBTN_LEFT;
		    break;
		    
		case SDL_BUTTON_RIGHT:
		    btn = MBTN_RIGHT;
		    break;
		    
		case SDL_BUTTON_MIDDLE:
		    btn = MBTN_MIDDLE;
		    break;
		    
		default:
		    btn = MBTN_OTHER;
	    }
	    
	    toReturn = new MouseEvent( btn, MOUSE_CLICKED, occurredX, occurredY );
	}
	break;
	
	case SDL_MOUSEBUTTONUP:
	{
	    MouseButton btn;
	    
	    switch( event.button.button )
	    {
		case SDL_BUTTON_LEFT:
		    btn = MBTN_LEFT;
		    break;
		    
		case SDL_BUTTON_RIGHT:
		    btn = MBTN_RIGHT;
		    break;
		    
		case SDL_BUTTON_MIDDLE:
		    btn = MBTN_MIDDLE;
		    break;
		    
		default:
		    btn = MBTN_OTHER;
	    }
	    
	    toReturn = new MouseEvent( btn, MOUSE_RELEASED, occurredX, occurredY );
	}
	break;
	
        case SDL_MOUSEMOTION:
	{
	    int relX = event.motion.xrel, relY = event.motion.yrel;
	    
	    toReturn = new MouseEvent( MBTN_NONE, MOUSE_MOTION, occurredX, occurredY, relX, relY );
	}
	break;
	
	default:
	break;
    }
    
    return toReturn;
}


/**
 * Creates a keyboard event based on an SDL_Event and returns it.
 */

KeyboardEvent* EventProcessor::ProcessKeyboardEvent(const SDL_Event &event)
{
    KeyboardEventType type;
    
    if( event.type == SDL_KEYDOWN )
    {
	type = KEY_PRESSED;
    }
    else if( event.type == SDL_KEYUP )
    {
	type = KEY_RELEASED;
    }
    else
    {
	return NULL;
    }
    
    return new KeyboardEvent( type, event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode );
}
    
    
